package com.jidong.test_springboot.shiro;

import java.util.Date;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator.Builder;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.jidong.test_springboot.util.JWTUtil;


/***
 *Authentication 是跟用户验证有关的。替换了authc的拦截器
 */
public class JWTFilter extends BasicHttpAuthenticationFilter{
	
	
	/*验证逻辑在这里写 (该怎么调用)  
	 * 这个方法是在ShiroConfig中的 的 map.put("/**", "jwt"); 这句话自动调用
	 * return true   代表本验证通过，还要继续其他验证
	 * return false  代表本验证通过，不必继续其他验证
	 * **/
	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
		String token=((HttpServletRequest)request).getHeader("Access-Token");//获取前端发来的token，要求前端必须要放到头里，
		JwtToken t=new JwtToken(token);
		SecurityUtils.getSubject().login(t);//login方法会自动调用Realm中的验证登录方法
		
		//在这里验证token是否快过期了，如果快过期了，赶紧生成一个新的token并发给前端 (前端得时刻更新token)

		if(checkIsTimeout(token)){//验证是否快过期，只有快过期的时候才重新生成token
			//根据用户名和密码生成新token
			String newtoken=JWTUtil.sign((String)t.getPrincipal(), (String)t.getCredentials());
			//给前端，下次访问的时候拿着新token
			HttpServletResponse resp=(HttpServletResponse)response;
			resp.setHeader("token", newtoken);//把新的token交给前端
			resp.setHeader("Access-Control-Expose-Headers", "token");//这个token是上面头的key
			// 结束
		}
		return true;
	}

	private boolean checkIsTimeout(String token) {
		long time=System.currentTimeMillis();//系统现在时间
		DecodedJWT jwt=JWT.decode(token);
		Date date=jwt.getExpiresAt();
		long tokenTime=date.getTime();
		if(tokenTime-time <1000*60*2) {//如果小于2分钟认为快过期
			return true;
		}
		return false;
	}
	
}
